import imghdr
from datetime import timedelta
import datetime
from django.core.paginator import Paginator
from django.db import transaction, DatabaseError
from django.shortcuts import render
from django.http import JsonResponse, HttpResponseBadRequest
# Create your views here.
from django.core.cache import cache
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection

from apps.homes.models import Area, House, Facility, HouseImage
import json

from apps.order.models import Order
from apps.users.models import User
from ihome import settings
from libs.qiniuyun.upload_file import storage


class AreasView(View):
    """城区数据"""

    def get(self, request):
        """提供城区数据"""
        # 判断是否有缓存列表
        area_list = cache.get('area_info')

        if not area_list:
            # 城区数据
            try:
                area_model_list = Area.objects.filter(name__isnull=False)

                # 序列化城区数据
                area_list = []
                for area_model in area_model_list:
                    area_list.append({'aid': area_model.id, 'aname': area_model.name})
            except Exception as e:
                return JsonResponse({'code': 400, 'errmsg': '城区数据有误'})

            # 提交缓存
            cache.set('area_info', area_list, 3600)

        # 返回响应
        return JsonResponse({
            "errmsg": "获取成功",
            "errno": "0",
            "data": area_list
        })


class ReleaseHouseView(View):
    """发布房源 房源搜索"""

    def get(self, request):
        """房源搜索"""

        # 获取参数
        aid = request.GET.get('aid')
        str_start_day = request.GET.get('sd')
        str_end_day = request.GET.get('ed')
        sort_key = request.GET.get('sk')
        page = request.GET.get('p')

        # 检查aid参数
        if not aid:
            return JsonResponse({"errno": 400, "errmsg": "参数错误"})

        # 检查page参数是否为整数
        try:
            page = int(page)
        except Exception as e:
            return JsonResponse({"errno": 400, "errmsg": "参数错误"})

        # 对日期进行相关处理
        try:
            start_day = None
            end_day = None
            if str_start_day:
                start_day = datetime.datetime.strptime(str_start_day, '%Y-%m-%d')
            if str_end_day:
                end_day = datetime.datetime.strptime(str_end_day, '%Y-%m-%d')
            # 判断结束时间是否大于开始时间
            if start_day and end_day:
                assert start_day < end_day, Exception('开始时间大于结束时间')
        except Exception as e:
            return JsonResponse({"errno": 400, "errmsg": "参数错误"})

        # 定义数组保存冲突的订单
        if start_day and end_day:
            # 开始时间　<　结束时间　＆＆　结束时间　>　开始时间
            conflict_order = Order.objects.filter(begin_date__lt=end_day, end_date__gt=start_day)
        elif start_day:
            # 结束时间　>　开始时间
            conflict_order = Order.objects.filter(end_date__gt=start_day)
        elif end_day:
            # 开始时间 < 结束时间
            conflict_order = Order.objects.filter(begin_date__lt=end_day)
        else:
            # 不存在冲突订单
            conflict_order = []

        # 获取冲突订单的房屋id
        conflict_house_id = []
        for order in conflict_order:
            conflict_house_id.append(order.house_id)


        # 查询数据
        if sort_key == 'booking':
            # 通过订单量降序排列
            houses_query = House.objects.filter(area_id=aid).exclude(id__in=conflict_house_id).order_by("-order_count")
        elif sort_key == 'price-inc':
            # 通过价格升序排列
            houses_query = House.objects.filter(area_id=aid).exclude(id__in=conflict_house_id).order_by("price")
        elif sort_key == 'price-des':
            # 通过价格降序排列
            houses_query = House.objects.filter(area_id=aid).exclude(id__in=conflict_house_id).order_by("-price")
        else:
            # 默认以最新的排序
            houses_query = House.objects.filter(area_id=aid).exclude(id__in=conflict_house_id).order_by("-create_time")

        paginator = Paginator(houses_query, 2)
        # 获取当前页对象
        page_houses = paginator.page(page)
        # 获取总页数
        total_page = paginator.num_pages
        # 遍历房屋数据
        houses = []
        for house in page_houses:
            houses.append({
                "address": house.address,
                "area_name": house.area.name,
                "ctime": house.create_time.strftime("%Y-%m-%d"),
                "house_id": house.id,
                "img_url": settings.QN_BASE_URL + house.index_image_url,
                "order_count": house.order_count,
                "price": house.price,
                "room_count": house.room_count,
                "title": house.title,
                "user_avatar": house.user.avatar.url
            }, )

        return JsonResponse({
            "errno": 0,
            "errmsg": "OK",
            "data": {
                "houses": houses,
                "total_page": total_page

            }
        })

    def post(self, request):
        """发布房源"""

        # 接收数据
        data = json.loads(request.body.decode())
        # 提取数据
        # 标题
        title = data.get('title')
        # 价格
        price = data.get('price')
        # 城区id
        area_id = data.get('area_id')
        # 房屋地址
        address = data.get('address')
        # 房间数目
        room_count = data.get('room_count')
        # 房屋面积
        acreage = data.get('acreage')
        # 房屋单元，如：几室几厅
        unit = data.get('unit')
        # 房屋容纳的人数
        capacity = data.get('capacity')
        # 房屋床铺的配置
        beds = data.get('beds')
        # 房屋押金
        deposit = data.get('deposit')
        # 最少入住天数
        min_days = data.get('min_days')
        # 最大入住天数，0表示不限制
        max_days = data.get('max_days')

        # 校验参数
        if not all([
            title, price, area_id, address, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days
        ]):
            return JsonResponse({"errno": "400", "errmsg": "缺少参数"})

        # 价格数据转换
        try:
            price = int(float(price) * 100)
            deposit = int(float(price) * 100)
        except Exception as e:
            return JsonResponse({"errno": "400", "errmsg": "参数错误"})

        # 判断城区id是否合法
        try:
            area_id = Area.objects.get(id=area_id)
        except Exception:
            return HttpResponseBadRequest('城区id错误')

        # 获取登录用户
        user = request.user
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                house = House.objects.create(
                    user=user,  # 用户id
                    area=area_id,  # 城区id
                    title=title,  # 标题
                    price=price,  # 单价，单位：分
                    address=address,  # 地址
                    room_count=room_count,  # 房间数目
                    acreage=acreage,  # 房屋面积
                    unit=unit,  # 房屋单元， 如几室几厅
                    capacity=capacity,  # 房屋容纳的人数
                    beds=beds,  # 房屋床铺的配置
                    deposit=deposit,  # 房屋押金
                    min_days=min_days,  # 最少入住天数
                    max_days=max_days,  # 最多入住天数，0表示不限制
                    # facility=facility,  # 和设施表之间多对多关系
                )
            except DatabaseError as e:
                # 添加失败，回滚
                transaction.savepoint_rollback(save_id)
                return HttpResponseBadRequest('数据添加失败')

            # 设施数据添加
            try:
                # 设施选择
                facility_id = data.get('facility')
                if facility_id:
                    facilitys = Facility.objects.filter(id__in=facility_id)
                    for facility in facilitys:
                        house.facility.add(facility)
            except DatabaseError as e:
                # 添加失败，回滚
                transaction.savepoint_rollback(save_id)
                return HttpResponseBadRequest('设施数据添加失败')

            # 添加成功，提交数据
            transaction.savepoint_commit(save_id)

        # 数据添加提交成功，返回响应
        return JsonResponse({
            "errno": "0",
            "errmsg": "发布成功",
            "data": {
                "house_id": house.id
            }
        })


class UploadImagesView(View):
    """上传房源图片"""

    def post(self, request, house_id):

        # 获取数据
        # 提取数据
        house_image = request.FILES.get("house_image")
        # 验证数据
        if not house_image:
            return JsonResponse({"errno": 400, "errmsg": "参数错误"})
        # 判断房间是否存在
        try:
            house = House.objects.get(id=house_id)
        except Exception as e:
            return JsonResponse({"errno": 400, "errmsg": "房间不存在"})

        # 文件名转换
        house_image_data = house_image.read()
        # 使用上传方法上传图片
        image_url = storage(house_image_data)
        # 拼接图片链接
        url = settings.QN_BASE_URL + image_url

        img_urls = []
        images = HouseImage.objects.filter(house=house)
        for image in images:
            img_urls.append(image.url)

        # 使用事务
        with transaction.atomic():
            # 保存图片到数据库中
            save_id = transaction.savepoint()
            try:
                if not house.index_image_url:
                    house.index_image_url = image_url
                    house.save()

                if image_url not in img_urls:
                    HouseImage.objects.create(
                        house_id=house_id,
                        url=image_url
                    )
                else:
                    # 添加失败 回滚
                    transaction.savepoint_rollback(save_id)
                    return JsonResponse({"errno": 400, "errmsg": "请勿上传相同的图片"})
            except Exception as e:
                # 添加失败 回滚
                transaction.savepoint_rollback(save_id)
                return JsonResponse({"errno": 400, "errmsg": "图片上传失败"})
            # 添加成功，提交
            transaction.savepoint_commit(save_id)

        # 返回响应
        return JsonResponse({
            "data": {
                "url": url,
            },
            "errno": "0",
            "errmsg": "图片上传成功"
        })


class MyHouseView(View):
    """我的房屋列表"""

    def get(self, request):
        # 获取用户
        user = request.user
        # 获取房屋信息
        try:
            ids = House.objects.filter(user=user)
        except Exception as e:
            return HttpResponseBadRequest('获取mysql数据出错')

        # 数据序列化
        houses = []
        for house in ids:
            houses.append({
                "address": house.address,
                "area_name": house.area_id,
                "ctime": house.create_time.strftime("%Y-%m-%d"),
                "house_id": house.id,
                "img_url": settings.QN_BASE_URL + house.index_image_url if house.index_image_url else "",
                "order_count": house.order_count,
                "price": house.price,
                "room_count": house.room_count,
                "title": house.title,
                "user_avatar": settings.QN_BASE_URL + str(house.user.avatar) + '.jpg' if house.user.avatar else "",
            })

        # 返回响应
        return JsonResponse({
            "data": {
                "houses": houses
            },
            "errmsg": "ok",
            "errno": "0"
        })


class HouseRecommendView(View):
    """首页房屋推荐"""

    def get(self, request):

        # 缓存判断
        house_list = cache.get('house_index')

        if not house_list:
            try:
                # 提取后五个房屋信息
                houses = House.objects.all()[:5]
            except Exception as e:
                return JsonResponse({"errno": "400", "errmsg": "查询数据失败"})

            # 序列化房屋信息
            house_list = []
            for house in houses:
                house_list.append({
                    "house_id": house.id,
                    "img_url": settings.QN_BASE_URL + house.index_image_url,
                    "title": house.title
                })

        # 将信息添加到缓存
        cache.set('house_index', house_list, 3600)
        # 返回响应
        return JsonResponse({
            "data": house_list,
            "errmsg": "OK",
            "errno": "0"
        })


class DetailView(View):
    """房屋详情页"""

    def get(self, request, house_id):

        try:
            # 查询房屋数据
            houses = House.objects.get(id=house_id)
        except Exception as e:
            return JsonResponse({"errno": "400", "errmsg": "查询数据失败"})

        # 获取订单数据
        orders = Order.objects.filter(house_id=houses.id)
        # 获取用户
        user = request.user

        # 判断用户是否已登录
        if not user.is_authenticated:
            user_id = -1
        else:
            user_id = user.id

        # 获取设施数据
        facilities_list = []
        facilities = houses.facility.all()
        for facilitie in facilities:
            facilities_list.append(facilitie.id)

        # 获取房屋图片
        img_urls = []
        images = HouseImage.objects.filter(house=houses)
        for image in images:
            img_urls.append(settings.QN_BASE_URL + image.url)

        # 获取评论列表
        comments_list = []
        for order in orders:
            if order.status == 4:
                comments_list.append({
                    "comment": order.comment,
                    "ctime": order.create_time.strftime("%Y-%m-%d"),
                    "user_name": order.user.username
                })

        # 返回数据生成
        data = {
            "house": {
                "acreage": houses.acreage,
                "address": houses.address,
                "beds": houses.beds,
                "capacity": houses.capacity,
                "comments": comments_list,
                "deposit": houses.deposit,
                "facilities": facilities_list,
                "hid": houses.id,
                "img_urls": img_urls,
                "max_days": houses.max_days,
                "min_days": houses.min_days,
                "price": houses.price,
                "room_count": houses.room_count,
                "title": houses.title,
                "unit": houses.unit,
                "user_avatar": houses.user.avatar.url,
                "user_id": houses.user.id,
                "user_name": houses.user.username
            },
            "user_id": user_id
        }

        # 返回响应
        return JsonResponse({
            "data": data,
            "errmsg": "OK",
            "errno": "0"
        })
